/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package infra;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JOptionPane;
import modelo.Cliente;
import modelo.Filme;
import modelo.Locacao;
import repositorio.AcervoDao;
import repositorio.ClientesDao;
import repositorio.LocacaoDao;
import servicos.*;
/**
 *
 * @author Edemilson Danker
 * @author Jefferson Sidney Rossetim
 * @author Rogerio Mello Vanti
 */
public class Locadora {

    private Historico historico;
    private List<Filme> acervo;
    private List<Cliente> clientes;
    private List<Locacao> locacoes;
    
    private ObjetoFactory fabrica;
    private static Locadora instancia;
    private List<LocadoraListener> ouvintes;
    private AcervoDao daoAcervo;
    private ClientesDao daoCliente;
    private LocacaoDao daoLocacao;
   
    private AssinaturaDSA dsa;
    
    
    private Locadora() throws FileNotFoundException, IOException, ClassNotFoundException {
        this.historico = new Historico();
        this.dsa = new AssinaturaDSA();
        this.ouvintes = new ArrayList();
        this.daoAcervo = new AcervoDao();
        this.daoCliente = new ClientesDao();
        this.daoLocacao = new LocacaoDao();
        this.fabrica = new ObjetoFactory();
        if (this.daoAcervo.verificarArquivo()) {
            this.acervo = this.daoAcervo.ler();
        } else {
            this.acervo = new ArrayList();
        }//fim else
        if (this.daoCliente.verificarArquivo()) {
            this.clientes = daoCliente.lerDoTexto();
        } else {
            this.clientes = new ArrayList();
        }//fim else
        if (this.daoLocacao.verificarArquivo()) {
            this.locacoes = this.daoLocacao.ler();
        } else {
            System.out.println("Criando nova lista de locações");
            this.locacoes = new ArrayList();
        }//fim else
    }//fim construtor

    public List<Filme> getAcervo() {
        return acervo;
    }

    public void setAcervo(List<Filme> acervo) {
        this.acervo = acervo;
    }

    public List<Cliente> getClientes() {
        return clientes;
    }

    public void setClientes(List<Cliente> clientes) {
        this.clientes = clientes;
    }

    public List<Locacao> getLocacoes() {
        return locacoes;
    }

    public void setLocacoes(List<Locacao> locacoes) {
        this.locacoes = locacoes;
    }

    public void adicionarOuvinte(LocadoraListener ouvinte) {
        this.ouvintes.add(ouvinte);
    }

    public void notificarFilme(String nome) {
        for (LocadoraListener l : this.ouvintes) {
            l.cadastrarFilme(nome);
        }//fim for
    }

    public void notificarCliente(String nome) {
        for (LocadoraListener l : this.ouvintes) {
            l.cadastrarCliente(nome);
        }//fim for
    }

    public void notificarLocacao(Locacao locacao) {
        for (LocadoraListener l : this.ouvintes) {
            l.cadastrarLocacao(locacao);
        }//fim for
    }

    public void salvar() throws FileNotFoundException, IOException {
        this.daoAcervo.escrever(this.acervo);
        this.daoCliente.escreverEmTexto(this.clientes);
        this.daoLocacao.escrever(this.locacoes); 
    }

    public static Locadora getInstancia() throws FileNotFoundException, IOException, ClassNotFoundException {
        if (instancia == null) {
            instancia = new Locadora();
        }//fim if
        return instancia;
    }

    public void locar(Cliente cliente, Filme filme){
        filme.setLocado(true);        
        Locacao l = new Locacao(cliente, new Date(), filme);
        this.locacoes.add(l);
        notificarLocacao(l);
        try{
            this.historico.escreverNoHistorico(l);
        }catch(Exception erro){
            System.out.println(erro.getMessage());
        }//fim catch
    }

    public List<Locacao> locacoesCliente(Cliente cliente) {
        ArrayList<Locacao> locacaoCliente = new ArrayList();
        for (Locacao l : this.locacoes) {
            if (l.getCliente().getNome().equals(cliente.getNome())) {
                locacaoCliente.add(l);
                
            }//fim if
        }//fim for
        return locacaoCliente;
    }
    
    
    public boolean verificarDSA(int indiceCliente, int indiceLocacao) {
        boolean ok = false;
        
        Cliente c = clientes.get(indiceCliente);
        Locacao l = locacoes.get(indiceLocacao);
        
        
        if(dsa.verificarAssinatura(c.getChavePublicaDSA(), 
           l.getFilmeLocados().getMensagem(),
           l.getFilmeLocados().getAssinatura() )){        
            
            ok = true;
           
        }
        
        return ok;
    }
    
    
    
     public void assinarDSA() {
       
        for (Cliente c:clientes) {
            KeyPair parChaves = dsa.gerarParChaves();
            c.setChavePublicaDSA(parChaves.getPublic());
            
            for(Locacao l: locacoes) {
                if(c.getNome().equals(l.getCliente().getNome())) {
                    l.getFilmeLocados().setMensagem(l.getFilmeLocados().getTitulo().getBytes());
                    l.getFilmeLocados().setAssinatura(l.getFilmeLocados().getMensagem());
                    l.getFilmeLocados().setAssinatura(dsa.assinar(parChaves.getPrivate(), l.getFilmeLocados().getAssinatura()));                    
                }             
                
            }     
            
            
        }//fim for
       
    }
    
    public Cliente getCliente(int indice) {
        return this.clientes.get(indice);
    }

    public Filme getFilme(int indice) {
        return this.acervo.get(indice);
    }

    public Locacao getLocacao(int indice) {
        return this.locacoes.get(indice);
    }

    public void removerCliente(int indice) {
        this.clientes.remove(indice);
    }

    public void removerFilme(int indice) {
        this.acervo.remove(indice);
    }

    public void devolver(Locacao locacao) {
        locacao.getFilmeLocados().setLocado(false);
        this.locacoes.remove(locacao);
    }

    public void cadastrarFilme(String titulo, String genero) {
        this.acervo.add(this.fabrica.criarFilme(titulo, genero));
        notificarFilme(titulo);
    }

    public void cadastrarCliente(String nome,String cpf, String numero) {
        try {
            this.clientes.add(this.fabrica.criarCliente(nome,cpf,numero));
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(Locadora.class.getName()).log(Level.SEVERE, null, ex);
        }
        notificarCliente(nome);
    }
}//fim class
//EOF